package com.ycl.test001;

/**
 * @author ycl
 * @date 2021/4/27 17:33
 * 死锁产生条件
 * 1.互斥 （共享资源只能被一个线程占用）
 * 2.占用且等待 （线程T1已经取得共享资源X，在等待共享资源Y时，线程T1不释放共享资源X）
 * 3.不可抢占 （其他线程不能抢占线程T1的共享资源）
 * 4.循环等待 （线程T1等待线程T2的占有资源，线程T2等待线程T1的占有资源，就是循环等待）
 */
public class Account {


    //余额
    private int balance;

    //actr应该为单例
    private Allocator actr;


    public int getBalance() {
        return balance;
    }

    public Account(int balance) {
        this.balance = balance;
    }

    //转账1（线程安全,由jvm保证锁的唯一性）
    void transfer1(Account target, int amt) {
        synchronized (Account.class) {
            if (this.balance >= amt) {
                this.balance -= amt;
                target.balance += amt;
            }
        }

    }

    //转账（会造成死锁）
    void transfer2(Account target, int amt) {
        synchronized (this) {
            synchronized (target) {
                if (this.balance >= amt) {
                    this.balance -= amt;
                    target.balance += amt;
                }
            }
        }
    }


    //转账（破坏占有且等待条件）
    void transfer(Account target, int amt) {
        //一次性申请转出账户和转入账户，知道成功
        while (!actr.apply(this, target)) ;
        try {
            //锁定转出账户
            synchronized (this) {
                //锁定转入账户
                synchronized (target) {
                    if (this.balance >= amt) {
                        this.balance -= amt;
                        target.balance += amt;
                    }
                }
            }
        } finally {
            //释放资源
            actr.free(this, target);
        }
    }

}
